﻿/*-------------------------------------------------------------------------
* 命名空间: XrayDirection.ViewModels/SettingsViewModel
* 类       名: SettingsViewModel
* 功      能:  TD
* 时      间:  2024/2/27 9:31:18
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using log4net.Util;
using OpenCvSharp;
using Prism.Commands;
using Prism.Mvvm;
using SiliconSelect.Common;
using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using VisionProcess;
using XrayDirection.Common;
using XrayDirection.DAL.DataEntity;
using XrayDirection.DAL.LocalDataAccess;
using XrayDirection.HelperManager;
using XrayDirection.Services;

namespace XrayDirection.ViewModels
{
    public class SettingsViewModel : BindableBase
    {
        public SettingsViewModel(IFileService fileService)
        {
            _fileService = fileService;
            LoadOriginalImageCommand = new DelegateCommand(DoLoadOriginalImageTask);
            SaveTemplateSizeCommand = new DelegateCommand(DoSaveTemplateSizeTask);
            LoadTemplateInfo();

            MoveCommand = new DelegateCommand<string>(DoMoveCommandTask);
            RotatedCommand = new DelegateCommand<string>(DoRotatedTask);
            KeepTemplateCommand = new DelegateCommand(DoKeepTemplateTask);
            OpenTemplateDirCommand = new DelegateCommand(DoOpenTemplateDirTask);
            MovePix = 20;
        }

        // 打开文件路径
        private void DoOpenTemplateDirTask()
        {
            FileDirHelper.OpenDirAndSelected(TemplateDirToOpen);
        }

        public DelegateCommand OpenTemplateDirCommand { get; private set; }


        public string TemplateDirToOpen = ConstantManager.TemplateDir01;

        /// <summary>
        /// 保存模板
        /// </summary>
        private void DoKeepTemplateTask()
        {
            // 首先是获取图像属于哪个Xray
            string imageNumber = ImageCapture.GetImageNumber(ImageLoadedName);
            if (imageNumber.Contains("01") && imageNumber.Contains("02"))
            {
                MessageProvider.ShowError(imageNumber, "图像名称错误,不知道要保存的模板属于哪个相机");
                return;
            }

            string templateDir = imageNumber.Contains("01") ? ConstantManager.TemplateDir01 : ConstantManager.TemplateDir02;
            TemplateDirToOpen = templateDir;
            string fileName = (Directory.GetFiles(templateDir).Length + 1).ToString() + ".bmp";
            Cv2.ImWrite(Path.Combine(templateDir, fileName), TemplateImageShow);
            ImageProcess.LoadTemplate(); // 重新加载一次模板
            MessageProvider.ShowInfo("模板保存成功", "操作成功提示框");
        }

        public DelegateCommand KeepTemplateCommand { get; private set; }

        /// <summary>
        /// 执行旋转命令
        /// </summary>
        /// <param name="obj"></param>
        private void DoRotatedTask(string rotatedDirection)
        {
            if (ImageOriginal != null && ImageShow != null)
            {
                double rotatedAngle = RotateAngle;
                if (rotatedDirection == "Clockwise")
                {
                    rotatedAngle = -RotateAngle;
                }

                Point2f center = new Point2f(ImageOriginal.Width / 2, ImageOriginal.Height / 2);
                Mat rotationMatrix = Cv2.GetRotationMatrix2D(center, rotatedAngle, 1.0);
                // 输出图像
                Mat dst = new Mat(ImageOriginal.Size(), ImageOriginal.Type());
                // 仿射变换
                Cv2.WarpAffine(ImageOriginal, dst, rotationMatrix, dst.Size(),
                    flags: InterpolationFlags.Linear, borderMode: BorderTypes.Reflect);
                // 最后把原始图像更改为这个图像
                ImageOriginal = dst;
                FlushImageShow();
            }
            else
            {
                MessageProvider.ShowError("请先加载原图片", "图片未加载提示框");
            }
        }

        public DelegateCommand<string> RotatedCommand { get; private set; }

        /// <summary>
        /// 旋转角度
        /// </summary>
        private double rotateAngle;

        public double RotateAngle
        {
            get { return rotateAngle; }
            set
            {
                rotateAngle = value;
                RaisePropertyChanged();
            }
        }



        /// <summary>
        /// 移动像素值
        /// </summary>
        /// <param name="obj"></param>
        private void DoMoveCommandTask(string opFlag)
        {
            if (MovePix == 0)
            {
                MessageProvider.ShowError("移动的像素值不能为空", "移动像素输入");
            }
            else
            {
                switch (opFlag)
                {
                    case "Left":
                        RectLeftStart.X = Math.Max(RectLeftStart.X - MovePix, 0);
                        break;
                    case "Right":
                        RectLeftStart.X = Math.Min(RectLeftStart.X + MovePix, ImageOriginal!.Width);
                        break;
                    case "Up":
                        RectLeftStart.Y = Math.Max(RectLeftStart.Y - MovePix, 0);
                        break;
                    case "Down":
                        RectLeftStart.Y = Math.Min(RectLeftStart.Y + MovePix, ImageOriginal!.Height);
                        break;
                }
                FlushImageShow();
            }
        }

        public DelegateCommand<string> MoveCommand { get; private set; }


        private int movePix;

        public int MovePix
        {
            get { return movePix; }
            set
            {
                movePix = value;
                RaisePropertyChanged();
            }
        }


        private void DoSaveTemplateSizeTask()
        {
            var result = WorkingInfoAccess.GetWorkingInfos();
            if (result.State)
            {
                WorkingInfoEntity workingInfo = result.Data![0];
                workingInfo.TemplateWidth = TemplateWidth;
                workingInfo.TemplateHeight = TemplateHeight;
                var updateRes = WorkingInfoAccess.UpdateWorkingInfo(workingInfo);
                if (updateRes.State)
                {
                    MessageProvider.ShowInfo("模板尺寸保存成功", "保存成功提示");
                    // 模板保存成功的时候,如果图像不为空的时候,就再次更新一次图像.
                    LoadTemplateInfo();
                    // 然后就是更新下图像
                    if (ImageShow != null && ImageOriginal != null)
                    {
                        FlushImageShow();
                    }
                }
                else
                {
                    MessageProvider.ShowError(updateRes.Message!, "workingInfo数据表更新失败");
                }
            }
            else
            {
                LogHelper.WriteLog("数据库操作异常" + result.Message!);
            }
        }

        // 刷新图像显示
        private void FlushImageShow()
        {
            Mat canvas = ImageOriginalColor!.Clone();
            Point endPoint = new Point(RectLeftStart.X + templateWidth, RectLeftStart.Y + templateHeight);
            Cv2.Rectangle(canvas, RectLeftStart, endPoint, RectColor, RectThickness);
            // 模板截取出来
            Rect roi = new Rect(RectLeftStart.X, RectLeftStart.Y, templateWidth, templateHeight);

            // 更新原图和模板
            ImageShow = canvas;
            TemplateImageShow = ImageOriginal[roi];
        }




        private Mat templateImageShow;

        public Mat TemplateImageShow
        {
            get { return templateImageShow; }
            set
            {
                templateImageShow = value;
                RaisePropertyChanged();
            }
        }



        public int RectThickness = 2;
        // 模板矩形块的颜色
        public Scalar RectColor = Scalar.Green;

        public DelegateCommand SaveTemplateSizeCommand { get; private set; }

        /// <summary>
        /// 加载模板信息,包括模板的宽和高
        /// </summary>
        private void LoadTemplateInfo()
        {
            var result = WorkingInfoAccess.GetWorkingInfos();
            if (result.State)
            {
                TemplateWidth = result.Data![0].TemplateWidth;
                TemplateHeight = result.Data![0].TemplateHeight;
            }
            else
            {
                LogHelper.WriteLog("数据库操作异常" + result.Message);
            }
        }


        private int templateWidth;

        public int TemplateWidth
        {
            get { return templateWidth; }
            set
            {
                templateWidth = value;
                RaisePropertyChanged();
            }
        }

        private int templateHeight;

        public int TemplateHeight
        {
            get { return templateHeight; }
            set
            {
                templateHeight = value;
                RaisePropertyChanged();
            }
        }


        private readonly IFileService _fileService;

        // 加载图像的任务,打开图像目录
        private void DoLoadOriginalImageTask()
        {
            string filePath = _fileService.ExploreFileDialog(ConstantManager.TemplateOriginalDir);
            if (!string.IsNullOrEmpty(filePath))
            {
                // 打开目录成功,并且选择了某个文件
                ImageLoadedName = Path.GetFileName(filePath);
                ImageOriginal = Cv2.ImRead(filePath, ImreadModes.Grayscale);
                // 直方图均衡化
                Mat imageEq = ImageProcess.GetHistImage(ImageOriginal);
                ImageOriginal = imageEq;
                // 应用  CLAHE
                //Mat imageClache = new Mat();
                //var cla = Cv2.CreateCLAHE(clipLimit: 2.0, tileGridSize: new Size(8, 8));
                //cla.Apply(ImageOriginal, imageClache);
                //ImageOriginal = imageClache;
                ImageOriginalColor = new Mat();
                Cv2.CvtColor(ImageOriginal, ImageOriginalColor!, ColorConversionCodes.GRAY2BGR);
                // 读取图像,并且按照模板去加载
                int width = ImageOriginal.Width;
                int height = ImageOriginal.Height;

                ImageWidth = width <= 800 ? width : 800;
                ImageHeight = height <= 600 ? height : 600;

                // 找到矩形的中心点
                int centerX = width / 2;
                int centerY = height / 2;

                // 矩形的尺寸
                int rectWidth = TemplateWidth;
                int rectHeight = TemplateHeight;

                // 计算矩形的左上角和右下角的坐标
                Point rectLeftStart = new Point(centerX - rectWidth / 2, centerY - rectHeight / 2);
                Point rectRightEnd = new Point(centerX + rectWidth / 2, centerY + rectHeight / 2);

                RectLeftStart = rectLeftStart;

                // 矩形框的颜色和粗细
                Scalar rectColor = Scalar.Red;
                int thickness = 2;
                // 在图像上绘制矩形,不能直接在ImageShow上绘制,因为你要给ImageShow赋值,前端才会更新,你直接绘制更改他的值
                // 但是并没有给前端通知更新,所以你也看不到的
                Mat canvas = ImageOriginalColor.Clone();
                if (canvas != null)
                {
                    Cv2.Rectangle(canvas!, rectLeftStart, rectRightEnd, rectColor, thickness);
                    ImageShow = canvas;
                }
            }
        }

        // 模板的左上角的点
        public Point RectLeftStart = new Point(0, 0);

        public DelegateCommand LoadOriginalImageCommand { get; private set; }

        // 加载的文件名称
        private string imageLoadedName = "图像未加载";

        public string ImageLoadedName
        {
            get { return imageLoadedName; }
            set
            {
                imageLoadedName = value;
                RaisePropertyChanged();
            }
        }

        /// <summary>
        /// 前端界面要显示的图像
        /// </summary>
        private Mat? imageShow;

        public Mat? ImageShow
        {
            get { return imageShow; }
            set
            {
                imageShow = value;
                RaisePropertyChanged();
            }
        }

        /// <summary>
        /// 加载的原始图像
        /// </summary>
        public Mat? ImageOriginal { get; set; }

        public Mat? ImageOriginalColor { get; set; }

        private int imageWidth;

        public int ImageWidth
        {
            get { return imageWidth; }
            set
            {
                imageWidth = value;
                RaisePropertyChanged();
            }
        }

        private int imageHeight;

        public int ImageHeight
        {
            get { return imageHeight; }
            set
            {
                imageHeight = value;
                RaisePropertyChanged();
            }
        }

    }
}
